﻿using System;
using System.Net;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Microsoft.Phone.Scheduler;
///
using ScheduleMVVM.Model.Miscellaneous;
using ScheduleMVVM.Model.PersistentFramework;
using ScheduleMVVM.Localization;

using GalaSoft.MvvmLight.Messaging;
using System.Collections;

namespace ScheduleMVVM.Model.RuntimeFramework
{
    /// <summary>
    /// Contains runtime application model-related data
    /// </summary>
    internal sealed class AdvancedRuntimeContext : RuntimeContext
    {
        // Binded collections
        /// <summary>
        /// Recent searches and favourites
        /// </summary>
        public List<RouteEntry> Recent
        {
            get
            {
                return recentXML.Value;
            }
        }
        // XML files - real storage
        private SyncableXml<List<RouteEntry>> recentXML;

        //private Random themeRandom;
        //private Int32 themeIndex;
        /// <summary>
        /// Departs in field updater
        /// </summary>
        public UpdateClock Clock
        { get; private set; }
        ///// <summary>
        ///// Suffix for PanoramaBackground and Color selection, e.g. "PanoramaBackground%ThemeIndex%"
        ///// </summary>
        //public Int32 ThemeIndex
        //{ get { return themeIndex; } }

        private static AdvancedRuntimeContext _self;
        /// <summary>
        /// Reference to the current instance of runtime context of the application
        /// </summary>
        public static AdvancedRuntimeContext Current
        {
            get
            {
                if (_self == null) _self = new AdvancedRuntimeContext();
                return _self;
            }
        }

        public AdvancedRuntimeContext()
            : base()
        {
            recentXML = new SyncableXml<List<RouteEntry>>("recent.xml");
            if (!favouritesXML.DataPresent)
            {
                favouritesXML.Value = new List<RouteEntry>();
#if DEBUG
                //// Sample favourite
                favouritesXML.Value.Add(new RouteEntry()
                {
                    Title = "из мск",
                    startStation = Stations.First<StationEntry>(x => x.id == 28604),
                    endStation = Stations.First<StationEntry>(x => x.id == 29304)
                });
                favouritesXML.Value.Add(new RouteEntry()
                {
                    Title = "в мск",
                    startStation = Stations.First<StationEntry>(x => x.id == 29304),
                    endStation = Stations.First<StationEntry>(x => x.id == 28704)
                });
                favouritesXML.Value.Add(new RouteEntry()
                {
                    Title = "в рио",
                    startStation = Stations.First<StationEntry>(x => x.id == 29304),
                    endStation = Stations.First<StationEntry>(x => x.id == 29204)
                });
                favouritesXML.Value.Add(new RouteEntry()
                {
                    Title = "из рио",
                    startStation = Stations.First<StationEntry>(x => x.id == 29204),
                    endStation = Stations.First<StationEntry>(x => x.id == 29304)
                });
#endif
                ////
                favouritesXML.Sync();
            }
            if (!recentXML.DataPresent) recentXML.Value = new List<RouteEntry>();
            // Background agent
#if UNSTABLE
            if (Settings.Current.EnableBackgroundAgent && !App.IsLowMemoryDevice)
            {
                PeriodicTask task = ScheduledActionService.Find("ScheduleMVVM.Agent") as PeriodicTask;
                if (task != null)
                {
                    ScheduledActionService.Remove("ScheduleMVVM.Agent");
                }
                task = new PeriodicTask("ScheduleMVVM.Agent");
                task.Description = GeneralResource.BackgroundAgentDescription;
                try
                {
                    ScheduledActionService.Add(task);

                }
                catch
                { }
#if DEBUG
                ScheduledActionService.LaunchForTest("ScheduleMVVM.Agent", TimeSpan.FromSeconds(10));
#endif
            }
#endif
            // Clock
            Clock = new UpdateClock();
            //// Theme support
            //themeRandom = new Random();
            //themeIndex = themeRandom.Next(1, 6);
            // Set message handler
            Messenger.Default.Register<UpdateContextCommand>(this, CommandDispatcher);
            Messenger.Default.Register<UpdateRouteViewCommand>(this, UpdateRouteEntry);
        }
        ///// <summary>
        ///// Sets new random theme index
        ///// </summary>
        //public void ThemeShuffle()
        //{
        //    themeIndex = themeRandom.Next(1, 6);
        //}
        /// <summary>
        /// Synchronizes favourites and recents with IsolatedStorage XMLs
        /// </summary>
        public void Synchronize()
        {
            favouritesXML.Sync();
            recentXML.Sync();
        }
        private void CommandDispatcher(UpdateContextCommand command)
        {
            switch (command.Action)
            {
                case UpdateContextCommandType.ADD:
                    Favourites.Add(command.Argument);
                    break;
                case UpdateContextCommandType.DELETE:
                    foreach (var i in Microsoft.Phone.Shell.ShellTile.ActiveTiles.ToArray()) // Unpin tiles
                    {
                        if (i.NavigationUri.OriginalString == "/") continue;
                        var entry = ParseTile(i);
                        if (entry == command.Argument)
                        {
                            i.Delete();
                        }
                    }
                    Favourites.Remove(command.Argument);
                    command.Argument.IsSearch = true;
                    foreach (var i in Recent.Where<RouteEntry>(
                        x => x.endStation.id == command.Argument.endStation.id && x.startStation.id == command.Argument.startStation.id
                        ))
                        i.IsSearch = true;

                    break;
                case UpdateContextCommandType.RENAME:
                    break;
                case UpdateContextCommandType.SORT:
                    if (Favourites.Remove(command.Argument))
                        Favourites.Insert(0, command.Argument);
                    break;
            }
            Messenger.Default.Send<ListChangedMessage>(new ListChangedMessage());
        }
        private void UpdateRouteEntry(UpdateRouteViewCommand command)
        {
            var entry = command.NewEntry.InnerValue;
            entry.LastAccessTime = DateTime.Now;
            foreach (var i in Recent.Where<RouteEntry>(
                        x => x.endStation.id == entry.endStation.id && x.startStation.id == entry.startStation.id
                        ).ToList())
                Recent.Remove(i);
            Recent.Insert(0, entry);
            Messenger.Default.Send<ListChangedMessage>(new ListChangedMessage());
        }
        // Static methods
        public static void OnLaunch()
        {
            GalaSoft.MvvmLight.Threading.DispatcherHelper.Initialize();
            Settings._self = InitializeSettings();
        }
        public static void OnActivation()
        {
            // Update departs in field
            Current.Clock.ForceTick();
            Messenger.Default.Send<OnActivatedCommand>(new OnActivatedCommand());
        }
        public static void OnDeactivation()
        {
            AdvancedRuntimeContext.Current.Synchronize();
            Settings.Current.Synchronize();
        }
        public static void OnTermination()
        {
            Current.Synchronize();
            Settings.Current.Synchronize();
        }
        private static Settings InitializeSettings()
        {
            var settingsDescriptor = new SyncableXml<Settings>("settings.xml");
            if (!settingsDescriptor.DataPresent)
                settingsDescriptor.CopyFromStream(App.GetResourceStream(new Uri(@"Prerequisites/DefaultSettings.xml", UriKind.Relative)).Stream);
            settingsDescriptor.Value.settingsXML = settingsDescriptor;
            settingsDescriptor.Value.Synchronize();
            return settingsDescriptor.Value;
        }
        public RouteEntry ParseTile(Microsoft.Phone.Shell.ShellTile Tile)
        {
            var Uri = Tile.NavigationUri;
            Int32 StartStationId = Int32.Parse(Uri.OriginalString.Split('?')[1].Split('&')[0].Split('=')[1]);
            Int32 EndStationId = Int32.Parse(Uri.OriginalString.Split('?')[1].Split('&')[1].Split('=')[1]);
            return GetFavouriteEntry(StartStationId, EndStationId);
        }
    }

}
